import pandas as pd
from feature_conf.config import GenericConfigConstant
import re
import phonenumbers
from datetime import datetime, timedelta


class SmsUtils:
    STOP_WORDS = {
        'mx': ['han', 'al', 'contra', 'esto', 'tengas', 'esta', 'eres', 'tú', 'nuestra', 'estuvieron', 'sois', 'con',
               'tuvo', 'estuvieses', 'esté', 'fuésemos', 'tendrán', 'sentida', 'también', 'ese', 'estad', 'nosotras',
               'tenga', 'vuestra', 'tuyo', 'e', 'nosotros', 'sería', 'porque', 'tuviese', 'estamos', 'seamos',
               'nuestro', 'sin', 'tenían', 'eran', 'poco', 'será', 'vuestros', 'hubiera', 'suya', 'desde', 'nos',
               'quien', 'su', 'tenidas', 'serás', 'estuvimos', 'les', 'estoy', 'suyos', 'estuvierais', 'sentid',
               'estuvieran', 'qué', 'habiendo', 'muchos', 'por', 'habida', 'tenida', 'fui', 'nuestras', 'mío',
               'estaban', 'tenía', 'fuese', 'sean', 'éramos', 'otro', 'algunas', 'habrán', 'tenemos', 'tuvisteis',
               'habríamos', 'hubo', 'nada', 'tendríamos', 'hubieran', 'teníais', 'son', 'esos', 'estuve', 'tenidos',
               'ellos', 'o', 'habidos', 'seríais', 'seré', 'estés', 'estaría', 'habréis', 'somos', 'esa', 'tenías',
               'teníamos', 'otros', 'hube', 'pero', 'estuvieseis', 'estada', 'tenéis', 'soy', 'tuviésemos', 'fueras',
               'estar', 'tengamos', 'este', 'mí', 'estuviese', 'míos', 'tuviera', 'una', 'entre', 'tiene', 'mi',
               'hubierais', 'habíais', 'estarás', 'ti', 'estaríamos', 'un', 'hubiéramos', 'él', 'más', 'seríamos',
               'tendría', 'le', 'tuviéramos', 'tuviesen', 'estaré', 'ante', 'sintiendo', 'las', 'mucho', 'se', 'ni',
               'hay', 'fuesen', 'habíamos', 'estuvo', 'estabas', 'es', 'suyo', 'estaremos', 'estuviste', 'tuvieseis',
               'habrías', 'estarías', 'serán', 'hubiesen', 'tuviste', 'el', 'habré', 'estuviesen', 'tus', 'tuvieron',
               'estáis', 'muy', 'estará', 'habrá', 'habías', 'seáis', 'hayáis', 'fuéramos', 'hayamos', 'todos', 'algo',
               'otras', 'habría', 'hubieses', 'hemos', 'habríais', 'para', 'otra', 'tanto', 'en', 'había', 'habrían',
               'quienes', 'a', 'estadas', 'los', 'tendrías', 'como', 'te', 'estuvisteis', 'tendrás', 'hubieron', 'haya',
               'sobre', 'estén', 'durante', 'serías', 'está', 'vuestro', 'ella', 'teniendo', 'fueseis', 'todo', 'yo',
               'tendremos', 'estéis', 'hubiste', 'estado', 'hubieras', 'tenido', 'del', 'tuyos', 'estuviésemos',
               'habido', 'tuvieran', 'era', 'tuyas', 'de', 'hayas', 'la', 'están', 'mis', 'estarán', 'estaréis',
               'habidas', 'suyas', 'tengáis', 'y', 'vuestras', 'vosotras', 'uno', 'estaba', 'erais', 'fuimos', 'siente',
               'serían', 'no', 'hubisteis', 'fue', 'ya', 'esas', 'estaríais', 'tendréis', 'cual', 'hubieseis', 'habéis',
               'antes', 'eras', 'estados', 'tienen', 'tuya', 'estas', 'ellas', 'seas', 'seremos', 'tuve', 'sentidas',
               'eso', 'tendrían', 'algunos', 'sentidos', 'estás', 'hayan', 'tengo', 'sentido', 'fueran', 'hubiese',
               'fuerais', 'estuviéramos', 'fuera', 'tened', 'donde', 'lo', 'tienes', 'hubiésemos', 'sea', 'estábamos',
               'habrás', 'estarían', 'he', 'fuisteis', 'nuestros', 'has', 'tendríais', 'tendrá', 'fueron', 'hubimos',
               'habían', 'sí', 'ha', 'tuvieras', 'vosotros', 'tuvierais', 'estemos', 'tu', 'os', 'mías', 'que',
               'estuvieras', 'estando', 'seréis', 'estuviera', 'sus', 'fuiste', 'fueses', 'tendré', 'tuvimos',
               'estabais', 'mía', 'tuvieses', 'unos', 'habremos', 'estos', 'tengan', 'me', 'hasta', 'cuando']

    }


def normalize_phone(phone, country_id):
    # 去掉phone中的非数字和非字母
    def phone_normalize(phone):
        if len(phone) == 0 or phone is None:
            return 0, '', ''
        if phone[0] == '+':
            phone = '+' + phone.replace('+', '').lstrip('0')
            length = len(phone) - 1
        else:
            phone = phone.lstrip('0')
            length = len(phone)
        is_vaild, country_code, national_phone = 0, '', phone.lstrip('+')

        if length < 7:
            return str(national_phone)

        try:
            if phone.startswith('+'):
                parse_info = phonenumbers.parse(phone)
            else:
                parse_info = phonenumbers.parse(phone, country_id.upper())

            # print(phonenumbers.is_valid_number(parse_info))
            is_vaild = 1 if phonenumbers.is_valid_number(parse_info) else 0
            if is_vaild:
                # country_code = parse_info.country_code
                national_phone = parse_info.national_number
                return str(national_phone)
        except Exception:
            pass
        return str(national_phone)

    phone = str(phone)
    try:
        if len(phone) == 0 or phone is None:
            return ''
        if phone[0] == '+':
            phone = '+' + ''.join(filter(str.isalnum, phone[1:])).lower()
        else:
            phone = ''.join(filter(str.isalnum, phone)).lower()  # 去掉phone中的非数字和非字母
    except Exception as e:
        pass
    if any(c.isalpha() for c in phone):
        return phone.replace('+', '')
    return phone_normalize(phone)


def time_trans(time, country_id):
    """
    时间转换
    :param time:  时间
    :param country_id: 国家id，如'mx'
    :return:  格式化后的时间
    """
    tz = GenericConfigConstant.COUNTRY_TIME_ZONE[country_id.lower()]
    time_len = len(str(time))
    time_format = "%a %b %d %H:%M:%S GMT%z %Y"
    if time_len == 10:
        format_time = datetime.utcfromtimestamp(int(time)) + timedelta(hours=tz)
    elif time_len == 13:
        format_time = datetime.utcfromtimestamp(int(time) // 1000) + timedelta(hours=tz)
    elif time_len == 34:
        format_time = datetime.strptime(str(time), time_format)
    else:
        format_time = datetime(2099, 12, 31, 23, 59, 59)

    return format_time


def process_sms_data(user_sms: pd.DataFrame,
                     apply_time: pd.Timestamp,
                     country_id: str):
    """
    处理传入的sms数据，list of json
    Args:
        user_sms:用户短信数据
        apply_time:申请时间
        country_id:国家id
    """

    assert country_id in GenericConfigConstant.COUNTRY_ID, "country id not in list, Please input correct country id"
    if user_sms is None or user_sms.shape[0] == 0:
        return pd.DataFrame(columns=['body', 'phone', 'read', 'src_phone', 'time', 'type', 'time_day', 'hour', 'weekday', 'month', 'words', 'sender'])
        

    user_sms = user_sms[user_sms['time'].apply(lambda x: len(str(x)) in [10, 13, 34])]
    user_sms.loc[:, 'time'] = user_sms['time'].apply(lambda x: time_trans(x, country_id))
    if isinstance(apply_time, str):
        apply_time = pd.Timestamp(apply_time)
    user_sms = user_sms[user_sms['time'] < apply_time]

    # 每个人选取最近的3000条短信
    user_sms = user_sms.sort_values(by='time', ascending=False).head(3000)
    user_sms['time'] = pd.to_datetime(user_sms['time'], errors='coerce')
    user_sms.dropna(subset=['time'], inplace=True) 

    user_sms['time_day'] = user_sms['time'].dt.date
    user_sms['hour'] = user_sms['time'].dt.hour
    user_sms['weekday'] = user_sms['time'].dt.weekday
    user_sms['month'] = user_sms['time'].dt.month

    # 对'body'字段进行预处理
    user_sms['body'] = user_sms['body'].apply(lambda x: x.lower())
    user_sms['words'] = user_sms['body'].apply(lambda x: set(re.compile(r'\b[Ññáéíóúü¡A-Za-z]+\b').findall(x)))
    user_sms['words'] = user_sms['words'].apply(
        lambda x: [i for i in x if i not in SmsUtils.STOP_WORDS[country_id]])
    user_sms['words'] = user_sms['words'].apply(lambda x: [i for i in x if len(i) > 2])
    user_sms['words'] = user_sms['words'].apply(lambda x: list(map(str, x)))
    user_sms['sender'] = user_sms['phone'].apply(lambda x: normalize_phone(x, country_id))
    return user_sms
